'''
Author       : mailnull 67731164@qq.com
Date         : 2024-07-23 22:59:55 +0800
LastEditors  : mailnull 67731164@qq.com
LastEditTime : 2024-07-29 01:03:27 +0800
FilePath     : views.py
Description  : 
Copyright (c) 2024 by mailnull email: 67731164@qq.com, All Rights Reserved.
'''
from uuid import uuid4
# from pathlib import Path
from sanic import Request, response, Websocket
from sanic import Blueprint
from sanic.response import HTTPResponse, ResponseStream
from sanic.log import logger
from aiohttp import ClientSession, ClientTimeout, WSMsgType
import asyncio

from apps.base.hunter import AppError
from settings import STATIC_PATH
import json

# import nest_asyncio


from  modules.xfyun import WSHandlerForChat, HTTPHandlerForChat

XUNFEI_Spark_Max_URL = "wss://spark-api.xf-yun.com/v3.5/chat"
XUNFEI_Spark_http_URL = "https://spark-api-open.xf-yun.com/v1/chat/completions"

message_bp = Blueprint("message", url_prefix="message", version=1)


#use ws://yourIP:8000/v1/message/chat?app_id=你的app_id&api_key=你的api_key&api_secret=你的api_secret
# /v1/message/chat
@message_bp.websocket("/chat")
async def chat(request: Request, ws: Websocket) -> None:
    args = request.args
    app_id = args.get("app_id")
    api_key = args.get("api_key")
    api_secret = args.get("api_secret")

    user_id = uuid4().hex
    #消息处理回调函数 我想把返回消息写在回调里。
    #暂时写在这里，后期再提出来
    async def recv_callback(reply, send_process, ins):
        if reply.type == WSMsgType.TEXT:
            data = json.loads(reply.data)
            code = data["header"]["code"]
            if code != 0:
                #这里加入raise
                print(code, data["header"]["message"])
                return
            choices = data["payload"]["choices"]
            status = choices["status"]
            seq = choices["seq"]
            content = choices["text"][0]["content"]
            # 生成json
            payload = json.dumps({"content":content})
            # await send_process.send(content)
            await send_process.send(payload)
            
            if status == 2:
                await ins.async_close_request_Protocol()
    
    async with ClientSession() as session:
        chatHandler = WSHandlerForChat(app_id, api_key, api_secret, XUNFEI_Spark_Max_URL, ws, session)
        async for msg in ws:
            await chatHandler.async_connect()
            await chatHandler.async_send_str(msg, user_id=user_id)
            await chatHandler.async_recv_data(callback=recv_callback)

#use http://yourIP:8000/v1/message/chat_http?app_id=你的app_id&api_key=你的api_key&你的api_secret
#使用[http POST]发送请求 
# /v1/message/chat_http
@message_bp.post("/chat_http")
async def chat_http(request:Request):
    args = request.args
    app_id = args.get("app_id")
    api_key = args.get("api_key")
    api_secret = args.get("api_secret")

    user_id = uuid4().hex
    #客户端发过来的消息
    msg = request.body.decode("utf-8")

    response = await request.respond(content_type="application/json")

    async def recv_callback(reply, send_process,ins):
        if reply.type == WSMsgType.TEXT:
            data = json.loads(reply.data)
            code = data["header"]["code"]
            if code != 0:
                #这里加入raise
                print(code, data["header"]["message"])
                return
            choices = data["payload"]["choices"]
            seq = choices["seq"]
            content = choices["text"][0]["content"]
            # 生成json
            payload = json.dumps({"content": content})
            await send_process.send(payload)
        
    chatHandler = WSHandlerForChat(app_id, api_key, api_secret, XUNFEI_Spark_Max_URL, response)
    await chatHandler.async_connect()
    await chatHandler.async_send_str(msg, user_id=user_id)
    await chatHandler.async_recv_data(callback=recv_callback)
    await chatHandler.async_close_session() # 主动关闭session(一次post创建一个session)
    #Optionally, you can explicitly end the stream by calling:
    return await response.eof()

@message_bp.post("/chat_with_http")
async def chat_with_http(request:Request):
    args = request.args
    app_id = args.get("app_id")
    api_key = args.get("api_key")
    api_secret = args.get("api_secret")
    #客户端发过来的消息
    msg = request.body.decode("utf-8")
    response = await request.respond(content_type="application/json")
    async def reply_callback(reply, send_process, ins):
        try:
            data = json.loads(reply)
            code = data["code"]
            if code != 0:
                print(F"\033[91m{code}: {data['message']}\033[0m")
                await send_process.send(json.dumps({"status": 500, "content": F"{code},{data['message']}"}))
                return
            choices = data["choices"]
            content = choices[0]["delta"]["content"]
            await send_process.send(json.dumps({"status": 200,"content":content}))
        except:
            await send_process.send(json.dumps({"status": 500, "content":F"error"}))
    
    async with ClientSession() as session:
        chatHandler = HTTPHandlerForChat(app_id, api_key, api_secret, XUNFEI_Spark_http_URL, response, session)
        await chatHandler.async_connect()
        await chatHandler.async_send_str(msg)
        await chatHandler.async_recv_data(reply_callback)
        # await chatHandler.async_close_session()
        
    return await response.eof()


